﻿using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Presentation;
using Microsoft.SPOT.Presentation.Controls;
using Microsoft.SPOT.Presentation.Media;
using Microsoft.SPOT.Touch;

using Gadgeteer.Networking;
using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;
using Gadgeteer.Modules.PeteBrown;
using Gadgeteer.Modules.GHIElectronics;

namespace GadgeteerMidiTest
{
    public partial class Program
    {
        // This method is run when the mainboard is powered up or reset.   

        private const MidiChannel Channel = MidiChannel.Channel01;

        void ProgramStarted()
        {
            // Use Debug.Print to show messages in Visual Studio's "Output" window during debugging.
            Debug.Print("Program Started");

            //TestNoteConversionUtility();

            leftButton.ButtonPressed += OnLeftButtonPressed;
            leftButton.ButtonReleased += OnLeftButtonReleased;

            rightButton.ButtonPressed += OnRightButtonPressed;
            rightButton.ButtonReleased += OnRightButtonReleased;

            midi.DebugPrintEnabled = true;

            midi.SoftThru = true;

            midi.MessageReceived += OnMidiMessageReceived;
            midi.EnableReceiver();

            SetupSequence();
        }

        StepSequencer _sequencer;
        private void SetupSequence()
        {
            _sequencer = new StepSequencer(midi, 32, new TimeSpan(0, 0, 0, 0, 250));

            // popcorn
            // (C) A# (C) G D# G C
            // (C) A# (C) G D# G C
            // (C) (D) (D#) (D) (D#) (C) (D) (C) (D) A# (C) A# (C) G# (C)
            _sequencer[0] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.C, 5), 100);
            _sequencer[1] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.ASharp, 4), 100);
            _sequencer[2] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.C, 5), 100);
            _sequencer[3] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.G, 4), 100);
            _sequencer[4] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.DSharp, 4), 100);
            _sequencer[5] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.G, 4), 100);
            _sequencer[6] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.C, 4), 100);
            _sequencer[7] = null;
            _sequencer[8] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.C, 5), 100);
            _sequencer[9] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.ASharp, 4), 100);
            _sequencer[10] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.C, 5), 100);
            _sequencer[11] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.G, 4), 100);
            _sequencer[12] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.DSharp, 4), 100);
            _sequencer[13] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.G, 4), 100);
            _sequencer[14] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.C, 4), 100);
            _sequencer[15] = null;
            _sequencer[16] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.C, 5), 100);
            _sequencer[17] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.D, 5), 127);
            _sequencer[18] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.DSharp, 5), 100);
            _sequencer[19] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.D, 5), 127);
            _sequencer[20] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.DSharp, 5), 100);
            _sequencer[21] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.C, 5), 127);
            _sequencer[22] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.D, 5), 127);
            _sequencer[23] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.C, 5), 100);
            _sequencer[24] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.D, 5), 127);
            _sequencer[25] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.ASharp, 4), 100);
            _sequencer[26] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.C, 5), 127);
            _sequencer[27] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.ASharp, 4), 100);
            _sequencer[28] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.C, 5), 127);
            _sequencer[29] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.GSharp, 4), 127);
            _sequencer[30] = new SequencerStep(Channel, MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.C, 5), 127);
            _sequencer[31] = null;
        }

        private bool _sequencePlaying = false;

        void OnLeftButtonPressed(Button sender, Button.ButtonState state)
        {
            if (_sequencePlaying)
                _sequencer.Stop();
            else
                _sequencer.Start();

            _sequencePlaying = !_sequencePlaying;
        }

        void OnLeftButtonReleased(Button sender, Button.ButtonState state)
        {
        }


        private int _currentProgramNumber = 0;
        void OnRightButtonReleased(Button sender, Button.ButtonState state)
        {
            _currentProgramNumber = (_currentProgramNumber + 1) % 127;

            midi.SendProgramChange(Channel, (byte)_currentProgramNumber);
        }

        void OnRightButtonPressed(Button sender, Button.ButtonState state)
        {
            //throw new NotImplementedException();
        }

        void OnMidiMessageReceived(MidiModule sender, MidiMessage message)
        {
            if (message.ID == MidiMessageId.ChannelNoteOn)
            {
                lED7R.TurnLightOn(1);
            }
            else if (message.ID == MidiMessageId.ChannelNoteOff)
            {
                lED7R.TurnLightOff(1);
            }
            else
            {
                lED7R.TurnLightOn(2);
            }
        }


        void TestNoteConversionUtility()
        {
            int octave = 0;

            Debug.Print("C(-1) = " + MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.C, -1));
            Debug.Print("C(0) = " + MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.C, 0));
            Debug.Print("A(2) = " + MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.A, 2));
            Debug.Print("C(4) = " + MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.C, 4));
            Debug.Print("C#(5) = " + MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.CSharp, 5));
            Debug.Print("Db(5) = " + MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.DFlat, 5));
            Debug.Print("C(9) = " + MidiUtility.NoteNameToMidiNoteNumber(MusicalNote.C, 9));

            for (int i = 0; i < 128; i += 8)
            {
                var note = MidiUtility.MidiNoteNumberToNameAndOctave((byte)i, out octave);

                Debug.Print("MIDI " + i + " = " + note + "(" + octave + ")");
            }


        }

    }
}
